from vcbrowser.engine.base import BaseEngine, EngineError
from vcbrowser.nodes import Node, FileNode, DirNode
from vcbrowser.enumerations import NodeKind, RepositoryType

try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO

import subvertpy
from subvertpy import ra
import posixpath
import time
import datetime
import logging

class SubvertpyEngine(BaseEngine):
    """
    Will use default config directory of subversion.
    As so it is needed that system has stored passwords
    to target remote repository first.
    """

    head_revision = -1

    def __init__(self, repo_url):
        super(SubvertpyEngine, self).__init__(repo_url)
        self.client = ra.RemoteAccess(repo_url)
    
    def get_kind(self, url, revision=head_revision):
        _kind = self.client.check_path(url, revision)
        if _kind == 1:
            kind = NodeKind.FILE
        elif _kind == 2:
            kind = NodeKind.DIR
        else:
            raise EngineError("Cannot define kind from url: '%s'" % url)
        return kind

    def _get_revision(self, revision):
        if revision is None:
            return SubvertpyEngine.head_revision
        elif isinstance(revision, int):
            return revision

    def request(self, url, revision=None, fetch_content=True):
        """
        Returns node from the given url with selected rev.
        """
        #super(SubvertpyEngine, self).request(url, revision, fetch_content)
        revision = self._get_revision(revision)
        kind = self.get_kind(url, revision)
        if kind is NodeKind.FILE:
            if fetch_content:
                content = self.get_file_content(url, revision)
            else:
                content = None
            requested_node = FileNode(url, content)
        elif kind is NodeKind.DIR:
            nodes = self.fetch_nodes(url, revision)
            dirents = [node for node in nodes if node.is_dir()]
            dirents.sort()
            filents = [node for node in nodes if node.is_file()]
            filents.sort()
            nodes = dirents + filents
            requested_node = DirNode(url, nodes)
        else:
            raise EngineError("Kind undefined!")
        return requested_node

    def get_file_content(self, url, revision=head_revision):
        container = StringIO()
        #logging.debug("Getting file's content from url '%s'" % rel_url)
        self.client.get_file(url, container, revision)
        container.seek(0)
        content = container.read()
        container.close()
        return content

    def fetch_nodes(self, url, revision=head_revision):
        _names, revnum, info = self.client.get_dir(url, revision)
        names = _names.keys()
        nodes = []
        for name in names:
            if url == '.':
                url = ''
            node_url = posixpath.join(url, name)
            kind = self.get_kind(node_url, revision)
            if kind is NodeKind.FILE:
                node = FileNode(node_url, content=None)
            elif kind is NodeKind.DIR:
                node = DirNode(node_url, nodes=[])
            nodes.append(node)
        return nodes

    def walk(self, topurl, revision=head_revision, fetch_files_content=False):
        """
        Similar to os.walk method. Insted of filesystem
        it walks through repository of the given topurl.
        Returns list of tuples (topnode, dirnodes, filenodes).
        """
        topnode = self.request(topurl, revision, fetch_content=fetch_files_content)
        if fetch_files_content:
            for filenode in topnode.files:
                filenode.content = self.get_file_content(filenode.url, revision)
        yield (topnode, topnode.dirs, topnode.files)
        for dirnode in topnode.dirs:
            for tup in self.walk(dirnode.url, revision, fetch_files_content):
                yield tup
        




    

